<?php


namespace app\admin\controller;


use app\admin\service\RbacService;
use app\common\controller\CommonController;
use app\common\enum\MainEnum;
use app\common\exception\NotFoundException;
use app\common\exception\ParameterFailedException;
use app\common\exception\RuntimeException;
use app\common\model\OrderListModel;
use app\common\model\OrderListRefundModel;
use app\common\model\OrderModel;
use app\common\model\PackageCompanyModel;
use app\common\model\UserModel;
use app\common\service\Lang;
use app\common\service\Office;
use app\common\service\Pay;
use app\common\validate\CommonValidate;
use app\common\validate\OrderValidate;
use app\Request;
use think\facade\Config;
use think\facade\Db;

class OrderController extends CommonController
{
    public function getOrderList(Request $request)
    {
        $searchParams = self::getParam([
            'nb',
            'package_nb',
            'receiver_name',
            'receiver_mobile_number',
            'create_time',
            'pay_time',
            'status',
        ]);
        $where        = [];
        foreach ($searchParams as $key => $value) {
            if (is_array($value) && $key === 'create_time') {
                $where[] = [
                    $key,
                    'between',
                    $value,
                ];
                continue;
            }
            if (strpos($value, '%') !== false) {
                $where[] = [
                    $key,
                    'like',
                    $value,
                ];
            }
            else {
                $where[] = [
                    $key,
                    '=',
                    $value,
                ];
            }
        }
        $where = self::getWhere($searchParams);

        $models    = (new OrderModel())->getOrderListPaginate($where, $this->page, $this->limit);
        $modelsArr = $models->toArray();
        return retJson(Lang::GETDone, $modelsArr);
    }

    public function getRefundList(Request $request)
    {
        //        $permissions  = RbacService::checkPermissions('admin');
        //        $searchParams = self::getParam([
        //            'nb',
        //            'status',
        //        ]);
        //        (new OrderValidate())->goCheck(__FUNCTION__, $searchParams);
        //        $where = self::getWhere($searchParams);
        //                vd($where,$searchParams);
        $where     = [];
        $models    = (new OrderListRefundModel())->getRefundList($where, $this->page, $this->limit);
        $modelsArr = $models->toArray();

        return retJson(Lang::GETDone, $modelsArr);
    }

    public function putRefundApprove(Request $request)
    {

        $params      = self::getParam([
            'refund_id',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new OrderListRefundModel())->where('id', $params['refund_id'])
                ->with(['orderInfo'])
                ->where('user_id', $request->userModel->getData('id'))
                ->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if ($model->getData('status') !== MainEnum::ORDER_LIST_REFUND_ING) {
                throw new ParameterFailedException(['msg' => '退款申请状态不正确']);
            }

            if ($model->getData('tk_type') === 1) {
                //退款类型：1退款；2退货退款
                $model->status           = MainEnum::ORDER_LIST_REFUND_WAIT_PAY;
                $model->approve_time     = NOW_TIME;
                $refundNb                = $model->getData('order_nb') . '_refund_id_' . $model->getData('id');
                $payRes                  = (new Pay())->refund($model->getData('order_nb'), $refundNb, $model->orderInfo->getData('price_pay'), $model->getData('refund_price'), $model->getData('reason'));
                $model->refund_no        = $refundNb;
                $model->refund_id        = $payRes['transaction_id'];
                $model->refund_total_fee = (float)$payRes['total_fee'] / 100;
                $model->refund_fee       = (float)$payRes['refund_fee'] / 100;
            }
            else {
                $model->status                 = MainEnum::ORDER_LIST_REFUND_DAILURU;
                $model->receiver_name          = '李国欣';
                $model->receiver_mobile_number = '15622535674';
                $model->receiver_address       = '这是地址';
                $model->approve_time           = NOW_TIME;
            }

            $model->save();

            Db::commit();

            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putRefundRefuse(Request $request)
    {

        $params      = self::getParam([
            'refund_id',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new OrderListRefundModel())->where('id', $params['refund_id'])
                ->with(['orderInfo'])
                ->where('user_id', $request->userModel->getData('id'))
                ->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if ($model->getData('status') !== MainEnum::ORDER_LIST_REFUND_ING) {
                throw new ParameterFailedException(['msg' => '退款申请状态不正确']);
            }

            $model->status      = MainEnum::ORDER_LIST_REFUND_REFUSE;
            $model->refuse_time = NOW_TIME;
            $model->save();

            Db::commit();

            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putRefundShouHuo(Request $request)
    {

        $params      = self::getParam([
            'refund_id',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new OrderListRefundModel())->where('id', $params['refund_id'])
                ->with(['orderInfo'])
                ->where('user_id', $request->userModel->getData('id'))
                ->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if ($model->getData('status') !== MainEnum::ORDER_LIST_REFUND_DAISHOUHUO) {
                throw new ParameterFailedException(['msg' => '退款申请状态不正确']);
            }

            $model->status = MainEnum::ORDER_LIST_REFUND_DAIYANHUO;
            $model->save();

            Db::commit();

            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putRefundYanhuo(Request $request)
    {

        $params      = self::getParam([
            'refund_id',
            'yanhuo_status',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);

        Db::startTrans();
        try {
            $model = (new OrderListRefundModel())->where('id', $params['refund_id'])
                ->with(['orderInfo'])
                ->where('user_id', $request->userModel->getData('id'))
                ->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if ($model->getData('status') !== MainEnum::ORDER_LIST_REFUND_DAIYANHUO) {
                throw new ParameterFailedException(['msg' => '退款申请状态不正确']);
            }

            if ($params['yanhuo_status'] === true) {
                $model->approve_time     = NOW_TIME;
                $refundNb                = $model->getData('order_nb') . '_refund_id_' . $model->getData('id');
                $payRes                  = (new Pay())->refund($model->getData('order_nb'), $refundNb, $model->orderInfo->getData('price_pay'), $model->getData('refund_price'), $model->getData('reason'));
                $model->refund_no        = $refundNb;
                $model->refund_id        = $payRes['transaction_id'];
                $model->refund_total_fee = (float)$payRes['total_fee'] / 100;
                $model->refund_fee       = (float)$payRes['refund_fee'] / 100;
                $model->status           = MainEnum::ORDER_LIST_REFUND_WAIT_PAY;
            }
            else {
                $model->refuse_time = NOW_TIME;
                $model->status      = MainEnum::ORDER_LIST_REFUND_REFUSE;
            }

            $model->save();

            Db::commit();

            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putOrderCancel(Request $request)
    {

        $params      = self::getParam([
            'id',
            'cancel_desc',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new OrderModel())->where('id', $params['id'])->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if ($model->getData('status') !== MainEnum::ORDER_STATUS_WAIT_PAY) {
                throw new ParameterFailedException(['msg' => '订单状态不正确']);
            }

            $model->status      = MainEnum::ORDER_STATUS_CANCEL;
            $model->cancel_desc = $params['cancel_desc'];
            $model->cancel_time = NOW_TIME;
            $model->save();

            Db::commit();

            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putOrderRefundConfirm(Request $request)
    {

        $params      = self::getParam([
            'id',
            'cancel_desc',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new OrderModel())->where('id', $params['id'])
                ->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if (!in_array($model->getData('status'), [
//                MainEnum::ORDER_STATUS_TK_DAISHENHE,
                MainEnum::ORDER_STATUS_WAIT_SHIPMENT,
            ], true)) {
                throw new ParameterFailedException(['msg' => '订单状态不正确']);
            }

            $payRes = (new Pay())->refund($model->getData('nb'), $model->getData('nb') . '_refund', $model->getData('price'), $model->getData('price'));
            //        groupRedpack	裂变红包	array $order	Collection
            /**
             * 'return_code' => string 'SUCCESS' (length=7)
             * 'return_msg' => string 'OK' (length=2)
             * 'appid' => string 'wxb3577ee5fac8bef0' (length=18)
             * 'mch_id' => string '1603840103' (length=10)
             * 'nonce_str' => string 'O6leMNEV0vxW1L1R' (length=16)
             * 'sign' => string '6B8C5E20EE063E972793BB998D141623' (length=32)
             * 'result_code' => string 'SUCCESS' (length=7)
             * 'transaction_id' => string '4200000814202011202665747271' (length=28)
             * 'out_trade_no' => string '20201120195fb7a2599c' (length=20)
             * 'out_refund_no' => string '20201120195fb7a2599crefund' (length=26)
             * 'refund_id' => string '50300706152020112204124729473' (length=29)
             * 'refund_channel' =>
             * array (size=0)
             * empty
             * 'refund_fee' => string '1' (length=1)
             * 'coupon_refund_fee' => string '0' (length=1)
             * 'total_fee' => string '1' (length=1)
             * 'cash_fee' => string '1' (length=1)
             * 'coupon_refund_count' => string '0' (length=1)
             * 'cash_refund_fee' => string '1' (length=1)
             */
            $model->status           = MainEnum::ORDER_STATUS_TK_DAIHUITUI;
            $model->cancel_desc      = $model->getData('cancel_desc') ?? $params['cancel_desc'];
            $model->cancel_time      = NOW_TIME;
            $model->refund_no        = $model->getData('nb') . '_refund';
            $model->refund_id        = $payRes['transaction_id'];
            $model->refund_total_fee = (float)$payRes['total_fee'] / 100;
            $model->refund_fee       = (float)$payRes['refund_fee'] / 100;
            //            $model->refund_status                = $payRes[''];
            //            $model->refund_settlement_refund_fee = $payRes[''];
            //            $model->refund_success_time   = $payRes[''];
            //            $model->refund_request_source = $payRes[''];

            $model->save();

            Db::commit();

            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putOrderFh(Request $request)
    {

        $params      = self::getParam([
            'id',
            'list_ids',
            'package_company_id',
            'package_nb',
            'receiver_name',
            'receiver_mobile_number',
            'receiver_address',
        ]);
        (new OrderValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            if (!is_array($params['list_ids'])) {
                $params['list_ids'] = explode(',', $params['list_ids']);
            }

            $where = [
                [
                    'id',
                    '=',
                    $params['id'],
                ],
            ];
            $model = (new OrderModel())->getOrder($where);
            if (!$model) {
                throw new NotFoundException();
            }

            $packageCompanyModel = PackageCompanyModel::where('id', $params['package_company_id'])->find();
            if (!$packageCompanyModel) {
                throw new NotFoundException(['msg' => '快递公司不存在']);
            }

            foreach ($params['list_ids'] as $list_id) {
                foreach ($model->orderListInfo as $orderList) {
                    if ($orderList->getData('id') === (int)$list_id) {
                        if (in_array($orderList->getData('status'), [
                            MainEnum::ORDER_LIST_REFUND_DONE,
                            MainEnum::ORDER_LIST_REFUND_WAIT_PAY,
                        ], true)) {
                            throw new ParameterFailedException(['msg' => '规格：' . $orderList->getData('product_sku_name') . '已退款，无法发货']);
                        }
                        $orderList->package_company_id     = $params['package_company_id'];
                        $orderList->package_nb             = $params['package_nb'];
                        $orderList->receiver_name          = $params['receiver_name'];
                        $orderList->receiver_mobile_number = $params['receiver_mobile_number'];
                        $orderList->receiver_address       = $params['receiver_address'];
                        $orderList->save();
                        continue 2;
                    }
                }
                throw new ParameterFailedException();
            }

            if (count($model->orderListInfo) === 1) {
                $model->status  = MainEnum::ORDER_STATUS_WAIT_SIGN_FOR;
                $model->fh_time = NOW_TIME;
            }
            elseif (count($model->orderListInfo) > 1) {
                $yes = true;
                foreach ($model->orderListInfo as $orderList) {
                    if (empty($orderList->getData('package_nb'))) {
                        $yes = false;
                    }
                }
                if ($yes) {
                    $model->status  = MainEnum::ORDER_STATUS_WAIT_SIGN_FOR;
                    $model->fh_time = NOW_TIME;
                }
            }
            else {
                throw new ParameterFailedException();
            }
            $model->save();
            //只有一条list数据的情况下，需要修改order
            //全部list的状态都是退款状态，需要修改order


            Db::commit();
            return retJson(Lang::PUTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function printTihuodan(Request $request)
    {

        //验证ids
        $params = self::getParam([
            'ids',
        ]);
        (new CommonValidate())->goCheck(__FUNCTION__, $params);
        //是否是中远ids，数量是否有误
        $ids       = explode(',', $params['ids']);
        $models    = (new SeaWaybillModel())->whereIn('id', $ids)->field([
            'id',
            'sea_waybill_number',
            'case_number',
            'box',
        ])->select();
        $modelsArr = $models->toArray();
        if (count($modelsArr) !== count($ids)) {
            throw new ParameterFailedException();
        }

        foreach ($modelsArr as $item) {
            if (stripos($item['sea_waybill_number'], 'P') !== 0) {
                throw new ParameterFailedException(['msg' => '必须是中远单才能下载']);
            }
        }

        //组合数据
        $array = [];
        foreach ($modelsArr as &$modelArr) {
            $seaWaybillNumberExists = false;
            foreach ($array as $sea_waybill_number => &$item) {
                //                var_dump(@$sea_waybill_number,$item);die;
                if ($sea_waybill_number === $modelArr['sea_waybill_number']) {
                    $seaWaybillNumberExists = true;
                    $boxExists              = false;
                    foreach ($item as &$v) {
                        if ($v['box'] === $modelArr['box']) {
                            var_dump('opk');
                            $v['count'] += 1;
                            continue 2;
                        }
                    }
                    if (!$boxExists) {
                        $array[$sea_waybill_number][] = [
                            'count' => 1,
                            'box'   => $modelArr['box'],
                        ];
                    }
                }
            }
            if (!$seaWaybillNumberExists) {
                $array[$modelArr['sea_waybill_number']] = [
                    [
                        'count' => 1,
                        'box'   => $modelArr['box'],
                    ],
                ];
            }
        }
        //组合成需要的数据
        $lastArray = [];
        foreach ($array as $sea_waybill_number => $v1) {
            foreach ($v1 as $v2) {
                $lastArray[] = [
                    'sea_waybill_number' => $sea_waybill_number,
                    'count'              => $v2['count'],
                    'box'                => $v2['box'],
                ];
            }
        }
        Office::tiHuoDan($lastArray);
        return retJson(Lang::GETDone);
    }

    public function copySeaWaybill(Request $request)
    {

        //验证ids
        $params = self::getParam([
            'ids',
        ]);
        (new CommonValidate())->goCheck(__FUNCTION__, $params);
        $ids = array_unique(explode(',', $params['ids']));
        if (count($ids) !== 1) {
            throw new ParameterFailedException(['msg' => '一次只能复制一个海运单']);
        }
        $model = (new SeaWaybillModel())->where('id', $ids[0])
            //            ->field([
            //                'id',
            //                'sea_waybill_number',
            //                'case_number',
            //                'box',
            //            ])
            ->find();
        if (!$model) {
            throw new ParameterFailedException(['msg' => '海运单不存在']);
        }

        if ($model->getData('car_dz_status') === '1' || $model->getData('dz_status') === '1') {
            throw new ParameterFailedException(['msg' => '对账后的海运单无法复制']);
        }

        $newModel                   = new SeaWaybillModel();
        $newModel->ship_company_id  = $model->getData('ship_company_id');
        $newModel->sail_schedule_id = $model->getData('sail_schedule_id');
        $newModel->dz_user_id       = $model->getData('dz_user_id');
        //        $newModel->car_id                 = $model->getData('car_id');
        //        $newModel->car_fee                 = $model->getData('car_fee');
        $newModel->sea_waybill_number     = $model->getData('sea_waybill_number');
        $newModel->goods_name             = $model->getData('goods_name');
        $newModel->towing_fee             = $model->getData('towing_fee');
        $newModel->need_receipt           = $model->getData('need_receipt');
        $newModel->need_poundbill         = $model->getData('need_poundbill');
        $newModel->type                   = $model->getData('type');
        $newModel->weight                 = $model->getData('weight');
        $newModel->receiver               = $model->getData('receiver');
        $newModel->receiver_mobile_number = $model->getData('receiver_mobile_number');
        $newModel->receiver_address       = $model->getData('receiver_address');
        $newModel->estimated_timestamp    = $model->getData('estimated_timestamp');
        $newModel->driver_true_name       = $model->getData('driver_true_name');
        $newModel->driver_mobile_number   = $model->getData('driver_mobile_number');
        $newModel->driver_id_card         = $model->getData('driver_id_card');
        $newModel->remark                 = $model->getData('remark');
        $newModel->fh_status              = $model->getData('fh_status');
        $newModel->status                 = $model->getData('status');

        $newModel->save();
        return retJson(Lang::POSTDone);
    }

    public function getDzList()
    {
        $models    = (new UserModel())->with([])
            ->whereOr('group_id', MainEnum::GROUP_Driver)
            ->whereOr('group_id', MainEnum::GROUP_ThirdPartyCompany)
            ->whereOr('group_id', MainEnum::GROUP_ShippingCompany)
            ->order([
                //            'sea_waybill_number' => 'desc',
                //            'case_number'        => 'desc',
                'create_time' => 'desc',
            ])
            ->paginate([
                'page'      => $this->page,
                'list_rows' => $this->limit,
            ]);
        $modelsArr = $models->toArray();
        $newRes    = [
            [
                'label'   => '船公司',
                'options' => [],
            ],
            [
                'label'   => '第三方合作公司或个人',
                'options' => [],
            ],
            [
                'label'   => '司机',
                'options' => [],
            ],
            [
                'label'   => '其他',
                'options' => [],
            ],
        ];
        foreach ($modelsArr['data'] as $item) {
            switch ($item['group_id']) {
                case MainEnum::GROUP_ShippingCompany:
                    $newRes[0]['options'][] = $item;
                    break;
                case MainEnum::GROUP_ThirdPartyCompany:
                    $newRes[1]['options'][] = $item;
                    break;
                case MainEnum::GROUP_Driver:
                    $newRes[2]['options'][] = $item;
                    break;
                default:
                    $newRes[3]['options'][] = $item;
            }
        }
        $modelsArr['el_options'] = $newRes;
        return retJson(Lang::GETDone, $modelsArr);
    }

    public function getSeaWaybillList(Request $request)
    {

        $params      = self::getParam([
            'sail_schedule_id',
            'ship_company_id',
            'dz_user_id',
            'car_id',
            'bill_id',
            'sea_waybill_number',
            'box',
            'case_number',
            'qf_number',
            'goods_name',
            'need_receipt',
            'need_poundbill',
            'type',
            'receiver',
            'receiver_mobile_number',
            'fh_status',
            'status',
            'create_time',
            'estimated_timestamp',
        ]);
        (new SeaWaybillValidate())->goCheck(__FUNCTION__, $params);
        $where = [];
        //        var_dump($params);die;
        foreach ($params as $key => $value) {
            if (is_array($value) && in_array($key, [
                    'create_time',
                    'estimated_timestamp',
                ], true)) {
                $where[] = [
                    $key,
                    'between',
                    $value,
                ];
                continue;
            }
            #進入where
            if (in_array($key, ['bill_id'], true)) {
                if ($value === 'null') {
                    $where[$key] = null;
                    continue;
                }
            }
            if (!in_array($value, [
                    '',
                    null,
                ], true) && $key !== 'ship_company_id') {

                $where[$key] = $value;
            }
        }
        $model    = (new SeaWaybillModel())->with([
            'shipCompanyInfo',
            'dzInfo',
            'billInfo',
            'carInfo',
            'driverInfo',
            'sailScheduleInfo',
        ])->where($where)->order([
            //            'sea_waybill_number' => 'desc',
            //            'case_number'        => 'desc',
            'create_time' => 'desc',
        ])->paginate([
            'page'      => $this->page,
            'list_rows' => $this->limit,
        ]);
        $modelArr = $model->toArray();
        foreach ($modelArr['data'] as &$item) {
            if (isset($item['sailScheduleInfo'])) {
                $item['sailScheduleInfo']['ship_name_voyage'] = $item['sailScheduleInfo']['ship_name'] . ' - ' . $item['sailScheduleInfo']['voyage'];
            }
        }
        return retJson(Lang::GETDone, $modelArr);
    }

    public function getExportStatement(Request $request)
    {
        //
        $params = self::getParam([
            'id',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new BillModel())->where('id', $params['id'])->with(['dzInfo'])->find();
            if (!$model) {
                throw new ParameterFailedException(['msg' => '账单不存在']);
            }

            $seaWaybillModels = (new SeaWaybillModel())->where('bill_id', $params['id'])->with(['carInfo'])->select();
            //            foreach ($seaWaybillModels as $seaWaybillModel) {
            //                if ($model->getData('type') === MainEnum::BILL_TYPE_CAR) {
            //                    if ($seaWaybillModel->getData('car_dz_status') !== MainEnum::SEA_WAYBILL_CAR_DZ_STATUS_RECONCILED) {
            //                        throw new ParameterFailedException(['msg' => '海运单：' . $seaWaybillModel->getData('sea_waybill_number') . '司机未对']);
            //                    }
            //                    continue;
            //                }
            //                if ($seaWaybillModel->getData('dz_status') !== MainEnum::SEA_WAYBILL_DZ_STATUS_RECONCILED) {
            //                    throw new ParameterFailedException(['msg' => '海运单：' . $seaWaybillModel->getData('sea_waybill_number') . '主体未对']);
            //                }
            //                continue;
            //            }
            //所有运单均已核对
            $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
            $spreadsheet->getActiveSheet()->getColumnDimension('A')->setWidth(20);
            $spreadsheet->getActiveSheet()->getColumnDimension('B')->setWidth(20);
            $spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth(15);
            $spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(10);
            $spreadsheet->getActiveSheet()->getColumnDimension('E')->setWidth(12);
            $spreadsheet->getActiveSheet()->getColumnDimension('F')->setWidth(15);
            $spreadsheet->getActiveSheet()->getColumnDimension('G')->setWidth(12);
            $spreadsheet->getActiveSheet()->getColumnDimension('J')->setWidth(20);
            $sheet = $spreadsheet->getActiveSheet();
            $title = [
                'TO:' . $model->dzInfo->getData('nickname'),
                'FM:湛江市赤坎运丰货运有限公司',
                'RE:运费明细',
            ];
            $row   = 1;
            $sheet->setCellValueByColumnAndRow(1, $row++, $title[0]);
            $sheet->setCellValueByColumnAndRow(1, $row++, $title[1]);
            $sheet->setCellValueByColumnAndRow(1, $row++, $title[2]);
            $seaWaybillInfo   = [];
            $seaWaybillInfo[] = [
                '送货时间',
                '海运单号',
                '箱号',
                '箱型',
                '货名',
                '收/装货地址',
                '车牌号',
                '拖车费',
                '其他费用',
                '其他费用说明',
            ];
            $totalTowingFee   = $totalOtherFee = 0;
            foreach ($seaWaybillModels as $seaWaybillModel) {
                $seaWaybillInfo[] = [
                    $seaWaybillModel->getData('estimated_timestamp'),
                    $seaWaybillModel->getData('sea_waybill_number'),
                    $seaWaybillModel->getData('case_number'),
                    $seaWaybillModel->getData('box'),
                    $seaWaybillModel->getData('goods_name'),
                    $seaWaybillModel->getData('receiver_address'),
                    $seaWaybillModel->carInfo->getData('plate_number'),
                    $seaWaybillModel->getData('towing_fee'),
                    $seaWaybillModel->getData('other_fee'),
                    $seaWaybillModel->getData('other_fee_desc'),
                ];
                $totalTowingFee   += $seaWaybillModel->getData('towing_fee');
                $totalOtherFee    += $seaWaybillModel->getData('other_fee');
            }
            $forNumber = count($seaWaybillInfo);
            for ($x = 0; $x < $forNumber; $x++) {
                $row++;
                $j = 1;
                foreach ($seaWaybillInfo[$x] as $k) {
                    $sheet->setCellValueByColumnAndRow($j++, $row, $k);
                }
            }
            $row++;
            $sheet->setCellValueByColumnAndRow(8, $row, $totalTowingFee);
            $sheet->setCellValueByColumnAndRow(9, $row++, $totalOtherFee);
            $sheet->setCellValueByColumnAndRow(8, $row++, '共计:' . ($totalTowingFee + $totalOtherFee));
            $sheet->setCellValueByColumnAndRow(1, $row++, '');
            $sheet->setCellValueByColumnAndRow(1, $row++, '');
            $sheet->setCellValueByColumnAndRow(1, $row++, '运费请付');
            $sheet->setCellValueByColumnAndRow(1, $row++, '开户行：工商银行广东湛江霞山支行');
            $sheet->setCellValueByColumnAndRow(1, $row++, '账 号：2015020509000181271');
            $sheet->setCellValueByColumnAndRow(1, $row++, '账 号：湛江市赤坎运丰货运有限公司');
            // Redirect output to a client’s web browser (Xlsx)
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment;filename="' . '运丰to' . $model->dzInfo->getData('nickname') . $model->title . '.xlsx"');
            header('Cache-Control: max-age=0');
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');

            // If you're serving to IE over SSL, then the following may be needed
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');              // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
            header('Cache-Control: cache, must-revalidate');               // HTTP/1.1
            header('Pragma: public');                                      // HTTP/1.0

            $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
            $writer->save('php://output');
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            throw $e;
        }
    }

    public function getBillList()
    {

        $params      = self::getParam([
            'type',
            'dz_user_id',
            'status',
            'create_time',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        $where = [];
        foreach ($params as $key => $value) {
            if (is_array($value) && $key === 'create_time') {
                $where[] = [
                    $key,
                    'between',
                    $value,
                ];
                continue;
            }
            if (!in_array($value, [
                    '',
                    null,
                ], true) && $key !== 'ship_company_id') {
                $where[$key] = $value;
            }
        }
        //                        var_dump($where, $params);
        //                        die;
        $model    = (new BillModel())->with([
            'dzInfo',
        ])->where($where)->order([
            //            'sea_waybill_number' => 'desc',
            //            'case_number'        => 'desc',
            'create_time' => 'desc',
        ])->paginate([
            'page'      => $this->page,
            'list_rows' => $this->limit,
        ]);
        $modelArr = $model->toArray();
        foreach ($modelArr['data'] as &$item) {
            $item['title_'] = $item['title'] . ' - ' . $item['dzInfo']['nickname'];
        }
        return retJson(Lang::GETDone, $modelArr);
    }

    public function putSeaWaybillCheck()
    {

        $params      = self::getParam([
            'ids',
            'checkType',
            'checked',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $ids       = explode(',', $params['ids']);
            $models    = (new SeaWaybillModel())->whereIn('id', $ids)->select();
            $modelsArr = $models->toArray();
            if (count($modelsArr) !== count($ids)) {
                throw new ParameterFailedException();
            }

            foreach ($models as $model) {
                if ($params['checkType'] === 'other') {
                    if ($model->getData('dz_user_id')) {
                        //船公司或个人
                        $model->dz_status = $params['checked'] ? MainEnum::SEA_WAYBILL_DZ_STATUS_RECONCILED : MainEnum::SEA_WAYBILL_DZ_STATUS_UNRECONCILED;
                        $model->save();
                        continue;
                    }
                    throw new ParameterFailedException(['msg' => '海运单：' . $model->getData('sea_waybill_number') . '未选择主体']);
                }

                if ($model->getData('car_id')) {
                    //司机
                    $model->car_dz_status = $params['checked'] ? MainEnum::SEA_WAYBILL_CAR_DZ_STATUS_RECONCILED : MainEnum::SEA_WAYBILL_CAR_DZ_STATUS_UNRECONCILED;
                    $model->save();
                    continue;
                }
                throw new ParameterFailedException(['msg' => '海运单：' . $model->getData('sea_waybill_number') . '未派遣司机']);
            }

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function getSailScheduleList()
    {

        $models      = (new SailScheduleModel())->with([
            'shipCompanyInfo',
        ])->order([
            //            'sea_waybill_number' => 'desc',
            //            'case_number'        => 'desc',
            'create_time' => 'desc',
        ])->paginate([
            'page'      => $this->page,
            'list_rows' => $this->limit,
        ]);
        $result      = $models->toArray();
        foreach ($result['data'] as &$item) {
            $item['ship_name_voyage'] = $item['ship_name'] . ' ' . $item['voyage'];
            if ($item['arrival_time']) {
                $item['ship_name_voyage'] .= ' 抵港日期：' . date('Y-m-d', strtotime($item['arrival_time']));
            }
            if ($item['shipment_time']) {
                $item['ship_name_voyage'] .= ' 装船日期：' . date('Y-m-d', strtotime($item['shipment_time']));
            }
        }
        return retJson(Lang::GETDone, $result);
    }

    public function postBillSeaWaybill()
    {

        $params      = self::getParam([
            'ids',
            'bill_id',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $ids       = explode(',', $params['ids']);
            $models    = (new SeaWaybillModel())->whereIn('id', $ids)->select();
            $modelsArr = $models->toArray();
            if (count($modelsArr) !== count($ids)) {
                throw new ParameterFailedException();
            }

            $billModel = (new BillModel())->where('id', $params['bill_id'])->find();
            if (!$billModel) {
                throw new ParameterFailedException(['msg' => '账单不存在']);
            }

            //账单状态如果客户已经审核，并且等待提交打款的时候，不允许修改
            if ($billModel->getData('status') !== MainEnum::BILL_STATUS_DEFAULT) {
                throw new ParameterFailedException(['msg' => '账单已经提交给客户审核或其他，无法更改']);
            }

            switch ($billModel->getData('type')) {
                case 'car':
                    foreach ($modelsArr as $item) {
                        //必须是已派送
                        if (!$item['car_id']) {
                            throw new ParameterFailedException(['msg' => '海运单：' . $item['sea_waybill_number'] . '未派遣司机']);
                        }
                        //账单主体必须一致
                        if ($item['car_own_user_id'] !== $billModel->getData('dz_user_id')) {
                            throw new ParameterFailedException(['msg' => '所有海运单必须是同一个主体']);
                        }
                    }
                    break;
                default:
                    foreach ($modelsArr as $item) {
                        //必须是已派送,账单主体必须一致
                        if (!$item['dz_user_id'] || $item['dz_user_id'] !== $billModel->getData('dz_user_id')) {
                            throw new ParameterFailedException(['msg' => '所有海运单必须是同一个主体']);
                        }
                    }
                    break;
            }
            (new SeaWaybillModel())->whereIn('id', $ids)->update(['bill_id' => $billModel->getData('id')]);

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function deleteBillSeaWaybill()
    {

        $params      = self::getParam([
            'ids',
            'bill_id',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $ids       = explode(',', $params['ids']);
            $models    = (new SeaWaybillModel())->whereIn('id', $ids)->select();
            $modelsArr = $models->toArray();
            if (count($modelsArr) !== count($ids)) {
                throw new ParameterFailedException();
            }

            $billModel = (new BillModel())->where('id', $params['bill_id'])->find();
            if (!$billModel) {
                throw new ParameterFailedException(['msg' => '账单不存在']);
            }

            //账单状态如果客户已经审核，并且等待提交打款的时候，不允许修改
            if ($billModel->getData('status') !== MainEnum::BILL_STATUS_DEFAULT) {
                throw new ParameterFailedException(['msg' => '账单已经提交给客户审核或其他，无法更改']);
            }

            switch ($billModel->getData('type')) {
                case 'car':
                    foreach ($modelsArr as $item) {
                        //必须是已派送
                        if (!$item['car_id']) {
                            throw new ParameterFailedException(['msg' => '海运单：' . $item['sea_waybill_number'] . '未派遣司机']);
                        }
                        //账单主体必须一致
                        if ($item['car_own_user_id'] !== $billModel->getData('dz_user_id')) {
                            throw new ParameterFailedException(['msg' => '所有海运单必须是同一个主体']);
                        }
                        if (!$item['bill_id']) {
                            throw new ParameterFailedException(['msg' => '海运单：' . $item['sea_waybill_number'] . '未加入账单']);
                        }
                    }
                    break;
                default:
                    foreach ($modelsArr as $item) {
                        //必须是已派送,账单主体必须一致
                        if (!$item['dz_user_id'] || $item['dz_user_id'] !== $billModel->getData('dz_user_id')) {
                            throw new ParameterFailedException(['msg' => '所有海运单必须是同一个主体']);
                        }
                        if (!$item['bill_id']) {
                            throw new ParameterFailedException(['msg' => '海运单：' . $item['sea_waybill_number'] . '未加入账单']);
                        }
                    }
                    break;
            }
            (new SeaWaybillModel())->whereIn('id', $ids)->update(['bill_id' => null]);

            Db::commit();
            return retJson(Lang::DELETEDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function postDispatchDriver()
    {

        $params      = self::getParam([
            'sea_waybill_id',
            'car_id',
            'car_fee',
        ]);
        (new SeaWaybillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            if ($params['car_fee'] && $params['car_fee'] <= (float)0) {
                throw new ParameterFailedException(['msg' => '金额不能<=0']);
            }
            $seaWaybillModel = (new SeaWaybillModel())->where('id', $params['sea_waybill_id'])->find();
            if (!$seaWaybillModel) {
                throw new ParameterFailedException(['msg' => '该运单不存在']);
            }

            if (!in_array((int)$seaWaybillModel->status, [
                MainEnum::SEA_WAYBILL_STATUS_UN_DISPATCH_CAR,
                MainEnum::SEA_WAYBILL_STATUS_DISPATCHING,
                //已经派送的单也可以进行修改
                //MainEnum::SEA_WAYBILL_STATUS_UPLOAD,如果已经有签收单就不能
            ], true)) {
                throw new ParameterFailedException(['msg' => '该运单状态无法继续操作']);
            }

            if ($params['car_id']) {
                $carModel = (new CarModel())->where('id', $params['car_id'])->find();
                if (!$carModel) {
                    throw new ParameterFailedException(['msg' => '该车辆不存在']);
                }
                $seaWaybillModel->car_own_user_id = $carModel->getData('beneficiary_id');
            }

            $seaWaybillModel->car_id  = $params['car_id'];
            $seaWaybillModel->status  = $params['car_id'] ? MainEnum::SEA_WAYBILL_STATUS_DISPATCHING : MainEnum::SEA_WAYBILL_STATUS_UN_DISPATCH_CAR;
            $seaWaybillModel->car_fee = $params['car_fee'] ?? 0.00;

            $seaWaybillModel->save();

            Db::commit();
            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function postUploadReceipt()
    {

        $params      = self::getParam([
            'id',
        ]);
        (new SeaWaybillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $seaWaybillModel = (new SeaWaybillModel())->where('id', $params['id'])->find();
            if (!$seaWaybillModel) {
                throw new ParameterFailedException(['msg' => '该运单不存在']);
            }

            if ($seaWaybillModel->status !== MainEnum::SEA_WAYBILL_STATUS_DISPATCHING) {
                throw new ParameterFailedException(['msg' => '该运单状态无法继续操作']);
            }

            $seaWaybillModel->status = MainEnum::SEA_WAYBILL_STATUS_UPLOADED_RECEIPT;

            $seaWaybillModel->save();

            Db::commit();
            return retJson(Lang::Done);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    /**
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/10/9
     * @Time: 10:20
     */
    public function postBill()
    {

        $params      = self::getParam([
            'title',
            'dz_user_id',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $oldModel = (new BillModel())->where('title', $params['title'])->find();
            if ($oldModel) {
                throw new ParameterFailedException(['msg' => '已存在该数据']);
            }

            $userModel = UserModel::where('id', $params['dz_user_id'])->find();
            if (!$userModel) {
                throw new ParameterFailedException(['msg' => '对账人不存在']);
            }

            $type = '';
            switch ($userModel->getData('group_id')) {
                case MainEnum::GROUP_ShippingCompany:
                case MainEnum::GROUP_ThirdPartyCompany:
                    $type = 'other';
                    break;
                case MainEnum::GROUP_Driver:
                    $type = 'car';
                    break;
                default:
                    throw new ParameterFailedException(['msg' => '对账人身份错误']);
            }
            $model             = new BillModel();
            $model->title      = $params['title'];
            $model->dz_user_id = $params['dz_user_id'];
            $model->type       = $type;

            $model->save();

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    /**
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/10/9
     * @Time: 10:20
     */
    public function putBill()
    {

        $params      = self::getParam([
            'id',
            'title',
            'dz_user_id',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new BillModel())->where('id', $params['id'])->find();
            if (!$model) {
                throw new ParameterFailedException(['msg' => '数据不存在']);
            }

            $userModel = UserModel::where('id', $params['dz_user_id'])->find();
            if (!$userModel) {
                throw new ParameterFailedException(['msg' => '对账人不存在']);
            }

            switch ($userModel->getData('group_id')) {
                case MainEnum::GROUP_ShippingCompany:
                case MainEnum::GROUP_ThirdPartyCompany:
                    $type = 'other';
                    break;
                case MainEnum::GROUP_Driver:
                    $type = 'car';
                    break;
                default:
                    throw new ParameterFailedException(['msg' => '对账人身份错误']);
            }
            $model->title      = $params['title'];
            $model->dz_user_id = $params['dz_user_id'];
            $model->type       = $type;

            $model->save();

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    /**
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/10/9
     * @Time: 10:20
     */
    public function putBillStatus()
    {

        $params      = self::getParam([
            'bill_id',
            'status',
        ]);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = (new BillModel())->where('id', $params['bill_id'])->find();
            if (!$model) {
                throw new ParameterFailedException(['msg' => '数据不存在']);
            }

            switch ($model->getData('status')) {
                case MainEnum::BILL_STATUS_DEFAULT:
                    if ($params['status'] !== MainEnum::BILL_STATUS_UN_PASS) {
                        throw new ParameterFailedException(['msg' => '账单状态有误']);
                    }
                    break;
                case MainEnum::BILL_STATUS_UN_PASS:
                    if (!in_array($params['status'], [
                        MainEnum::BILL_STATUS_DEFAULT,
                        MainEnum::BILL_STATUS_UN_PAY,
                    ], true)) {
                        throw new ParameterFailedException(['msg' => '账单状态有误']);
                    }
                    break;
                case MainEnum::BILL_STATUS_UN_PAY:
                    if (!in_array($params['status'], [
                        MainEnum::BILL_STATUS_UN_PASS,
                        MainEnum::BILL_STATUS_UN_VALIDATE,
                    ], true)) {
                        throw new ParameterFailedException(['msg' => '账单状态有误']);
                    }
                    break;
                case MainEnum::BILL_STATUS_UN_VALIDATE:
                    if (!in_array($params['status'], [
                        MainEnum::BILL_STATUS_UN_PAY,
                        MainEnum::BILL_STATUS_DONE,
                    ], true)) {
                        throw new ParameterFailedException(['msg' => '账单状态有误']);
                    }
                    break;
                default:
                    if ($params['status'] !== MainEnum::BILL_STATUS_DONE) {
                        throw new ParameterFailedException(['msg' => '账单已经确认无法更改']);
                    }
                    break;
            }

            $model->status = $params['status'];

            $model->save();

            Db::commit();
            return retJson(Lang::PUTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function deleteBill()
    {

        $params      = self::getParam(['id']);
        (new BillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = BillModel::where('id', $params['id'])->find();
            if (!$model) {
                throw new NotFoundException();
            }

            //            $otherModel = OtherModel::where('id', $params['id'])->find();
            //            if (!$otherModel) {
            //                throw new NotFoundException();
            //            }

            $model->delete_time = NOW_TIME;
            $model->save();

            Db::commit();

            return retJson(Lang::DELETEDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function postSeaWaybill()
    {

        $params      = self::getParam([
            'sea_waybill_number',
            'case_number',
            'qf_number',
            'box',
            'sail_schedule_id',
            'towing_fee',
            'other_fee',
            'other_fee_desc',
            'car_id',
            'car_fee',
            'goods_name',
            'weight',
            'receiver',
            'receiver_mobile_number',
            'receiver_address',
            'need_receipt',
            'need_poundbill',
            'fh_status',
            'remark',
            'estimated_timestamp',
            'type',
            'dz_user_id',
        ]);
        (new SeaWaybillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $oldSeaWaybillModel = (new SeaWaybillModel())->where('sea_waybill_number', $params['sea_waybill_number'])
                ->where('case_number', $params['case_number'])
                ->where('type', $params['type'])
                ->find();
            if ($oldSeaWaybillModel) {
                throw new ParameterFailedException(['msg' => '已存在该运单']);
            }

            if ($params['car_id'] !== null) {
                $carModel = (new CarModel())->where('id', $params['car_id'])->find();
                if (!$carModel) {
                    throw new ParameterFailedException(['msg' => '车辆不存在']);
                }
                if (!$carModel->getData('driver_id')) {
                    throw new ParameterFailedException(['msg' => '车辆未绑定司机']);
                }
            }

            $sailScheduleModel = SailScheduleModel::where('id', $params['sail_schedule_id'])->find();

            if (!$sailScheduleModel) {
                throw new ParameterFailedException(['msg' => '该船期不存在']);
            }

            if ($params['dz_user_id']) {
                $thirdPartyCompanyModel = UserModel::where('id', $params['dz_user_id'])
                    ->where('group_id', MainEnum::GROUP_ThirdPartyCompany)
                    ->find();

                if (!$thirdPartyCompanyModel) {
                    throw new ParameterFailedException(['msg' => '合作的第三方公司或个人不存在']);
                }
            }

            $importModel                         = new SeaWaybillModel();
            $importModel->ship_company_id        = $sailScheduleModel->ship_company_id;
            $importModel->sail_schedule_id       = $params['sail_schedule_id'];
            $importModel->sea_waybill_number     = $params['sea_waybill_number'];
            $importModel->box                    = $params['box'];
            $importModel->receiver_address       = $params['receiver_address'];
            $importModel->case_number            = $params['case_number'];
            $importModel->qf_number              = $params['qf_number'];
            $importModel->goods_name             = $params['goods_name'];
            $importModel->towing_fee             = $params['towing_fee'];
            $importModel->other_fee_desc         = $params['other_fee_desc'];
            $importModel->need_receipt           = $params['need_receipt'];
            $importModel->need_poundbill         = $params['need_poundbill'];
            $importModel->status                 = $params['car_id'] ? MainEnum::SEA_WAYBILL_STATUS_DISPATCHING : MainEnum::SEA_WAYBILL_STATUS_UN_DISPATCH_CAR;
            $importModel->car_id                 = $params['car_id'];
            $importModel->car_fee                = $params['car_fee'] ?? 0.00;
            $importModel->other_fee              = $params['other_fee'] ?? 0.00;
            $importModel->weight                 = $params['weight'];
            $importModel->type                   = $params['type'];
            $importModel->receiver               = $params['receiver'];
            $importModel->receiver_mobile_number = $params['receiver_mobile_number'];
            $importModel->remark                 = $params['remark'];
            $importModel->dz_user_id             = $params['dz_user_id'];
            $importModel->fh_status              = $params['fh_status'];
            if ($params['car_id'] !== null) {
                $importModel->car_own_user_id = $carModel->getData('beneficiary_id');
            }
            if ($params['estimated_timestamp']) {
                $importModel->estimated_timestamp = $params['estimated_timestamp'];
            }
            $importModel->save();

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putSeaWaybill()
    {

        $params      = self::getParam([
            'id',
            'sea_waybill_number',
            'case_number',
            'qf_number',
            'box',
            'sail_schedule_id',
            'towing_fee',
            'other_fee',
            'other_fee_desc',
            'car_id',
            'car_fee',
            'goods_name',
            'weight',
            'receiver',
            'receiver_mobile_number',
            'receiver_address',
            'need_receipt',
            'need_poundbill',
            'fh_status',
            'remark',
            'estimated_timestamp',
            'type',
            'dz_user_id',
        ]);
        //        var_dump($params);die;

        (new SeaWaybillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $oldSeaWaybillModel = (new SeaWaybillModel())->where('id', $params['id'])->find();
            if (!$oldSeaWaybillModel) {
                throw new NotFoundException(['msg' => '该运单不存在']);
            }

            $sailScheduleModel = SailScheduleModel::where('id', $params['sail_schedule_id'])->find();
            if (!$sailScheduleModel) {
                throw new ParameterFailedException(['msg' => '该船期不存在']);
            }

            if ($params['dz_user_id']) {
                $thirdPartyCompanyModel = UserModel::where('id', $params['dz_user_id'])
                    ->where('group_id', MainEnum::GROUP_ThirdPartyCompany)
                    ->find();

                if (!$thirdPartyCompanyModel) {
                    throw new ParameterFailedException(['msg' => '合作的第三方公司或个人不存在']);
                }
            }

            if ($params['car_id'] !== null) {
                $carModel = (new CarModel())->where('id', $params['car_id'])->find();
                if (!$carModel) {
                    throw new ParameterFailedException(['msg' => '车辆不存在']);
                }
                if (!$carModel->getData('driver_id')) {
                    throw new ParameterFailedException(['msg' => '车辆未绑定司机']);
                }
            }

            $oldSeaWaybillModel->ship_company_id    = $sailScheduleModel->ship_company_id;
            $oldSeaWaybillModel->sail_schedule_id   = $params['sail_schedule_id'];
            $oldSeaWaybillModel->sea_waybill_number = $params['sea_waybill_number'];
            $oldSeaWaybillModel->box                = $params['box'];
            $oldSeaWaybillModel->receiver_address   = $params['receiver_address'];
            $oldSeaWaybillModel->case_number        = $params['case_number'];
            $oldSeaWaybillModel->qf_number          = $params['qf_number'];
            $oldSeaWaybillModel->goods_name         = $params['goods_name'];
            $oldSeaWaybillModel->towing_fee         = $params['towing_fee'];
            $oldSeaWaybillModel->other_fee_desc     = $params['other_fee_desc'];
            $oldSeaWaybillModel->need_receipt       = $params['need_receipt'];
            $oldSeaWaybillModel->need_poundbill     = $params['need_poundbill'];
            $oldSeaWaybillModel->status             = $params['car_id'] ? MainEnum::SEA_WAYBILL_STATUS_DISPATCHING : MainEnum::SEA_WAYBILL_STATUS_UN_DISPATCH_CAR;
            $oldSeaWaybillModel->car_id             = $params['car_id'];
            $oldSeaWaybillModel->car_fee            = $params['car_fee'] ?? 0.00;
            $oldSeaWaybillModel->other_fee          = $params['other_fee'] ?? 0.00;
            $oldSeaWaybillModel->weight             = $params['weight'];
            //            if ($params['need_poundbill'] !== null) {
            //                $oldSeaWaybillModel->need_poundbill = $params['need_poundbill'];
            //            }
            $oldSeaWaybillModel->type                   = $params['type'];
            $oldSeaWaybillModel->receiver               = $params['receiver'];
            $oldSeaWaybillModel->receiver_mobile_number = $params['receiver_mobile_number'];
            $oldSeaWaybillModel->remark                 = $params['remark'];
            $oldSeaWaybillModel->dz_user_id             = $params['dz_user_id'];
            $oldSeaWaybillModel->fh_status              = $params['fh_status'];
            if ($params['estimated_timestamp']) {
                $oldSeaWaybillModel->estimated_timestamp = $params['estimated_timestamp'];
            }
            $oldSeaWaybillModel->save();

            Db::commit();
            return retJson(Lang::PUTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function deleteSeaWaybill()
    {

        $params      = self::getParam(['id']);
        (new SeaWaybillValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = SeaWaybillModel::where('id', $params['id'])->find();
            if (!$model) {
                throw new NotFoundException();
            }

            if ($model->car_dz_status === '1') {
                throw new RuntimeException(['msg' => '该运单司机已对账，不可删除']);
            }

            if ($model->dz_status === '1') {
                throw new RuntimeException(['msg' => '该运单已对账，不可删除']);
            }

            $model->delete_time = NOW_TIME;
            $model->save();

            Db::commit();

            return retJson(Lang::DELETEDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function postSailSchedule()
    {

        $params      = self::getParam([
            'ship_name',
            'voyage',
            'ship_company_id',
            'arrival_time',
            'unloading_time',
            'shipment_time',
        ]);
        (new SailScheduleValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $oldSailScheduleModel = (new SailScheduleModel())->where('ship_name', $params['ship_name'])
                ->where('voyage', $params['voyage'])
                ->find();
            if ($oldSailScheduleModel) {
                throw new ParameterFailedException(['msg' => '已存在该船期']);
            }

            $shipCompanyModel = (new UserModel())->where('id', $params['ship_company_id'])
                ->where('group_id', MainEnum::GROUP_ShippingCompany)
                ->find();
            if (!$shipCompanyModel) {
                throw new ParameterFailedException(['msg' => '船公司不存在']);
            }

            $sailScheduleModel                  = new SailScheduleModel();
            $sailScheduleModel->ship_name       = $params['ship_name'];
            $sailScheduleModel->voyage          = $params['voyage'];
            $sailScheduleModel->ship_company_id = $params['ship_company_id'];
            $sailScheduleModel->arrival_time    = $params['arrival_time'];
            $sailScheduleModel->unloading_time  = $params['unloading_time'];
            $sailScheduleModel->shipment_time   = $params['shipment_time'];

            $sailScheduleModel->save();

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putSailSchedule()
    {

        $params      = self::getParam([
            'id',
            'ship_name',
            'voyage',
            'ship_company_id',
            'arrival_time',
            'unloading_time',
            'shipment_time',
        ]);
        (new SailScheduleValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $sailScheduleModel = SailScheduleModel::where('id', $params['id'])->find();
            if (!$sailScheduleModel) {
                throw new NotFoundException();
            }

            $shipCompanyModel = (new UserModel())->where('id', $params['ship_company_id'])
                ->where('group_id', MainEnum::GROUP_ShippingCompany)
                ->find();

            if (!$shipCompanyModel) {
                throw new ParameterFailedException(['msg' => '船公司不存在']);
            }

            $sailScheduleModel->ship_name       = $params['ship_name'];
            $sailScheduleModel->voyage          = $params['voyage'];
            $sailScheduleModel->ship_company_id = $params['ship_company_id'];
            $sailScheduleModel->arrival_time    = $params['arrival_time'];
            $sailScheduleModel->unloading_time  = $params['unloading_time'];
            $sailScheduleModel->shipment_time   = $params['shipment_time'];

            $sailScheduleModel->save();

            Db::commit();
            return retJson(Lang::PUTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function deleteSailSchedule()
    {

        $params      = self::getParam(['id']);
        (new SailScheduleValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $model = SailScheduleModel::where('id', $params['id'])->find();
            if (!$model) {
                throw new NotFoundException();
            }

            $seaWaybillModel = (new SeaWaybillModel())->where('ship_company_id', $model->ship_company_id)->find();

            if ($seaWaybillModel) {
                throw new ParameterFailedException(['msg' => '该船期下存在海运单，无法删除']);
            }
            //var_dump($sailScheduleModel->toArray());die;
            $model->delete_time = NOW_TIME;
            $model->save();

            Db::commit();

            return retJson(Lang::DELETEDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function postImportZhongguSeaWaybill(): void
    {
        //检查船期是否存在，不存在则创建
        Db::startTrans();
        try {
            $spreadsheet   = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
            $reader        = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx'); //设置以Excel5格式(Excel97-2003工作簿)
            $PHPExcel      = $reader->load('1.xlsx');                                   // 载入excel文件
            $sheet         = $PHPExcel->getSheet(0);                                    // 读取第一個工作表
            $highestRow    = $sheet->getHighestRow();                                   // 取得总行数
            $highestColumm = $sheet->getHighestColumn();                                // 取得总列数
            $data          = [];
            $ship_name     = trim($sheet->getCell('A1')->getValue());
            $voyage        = trim($sheet->getCell('B1')->getValue());
            $c             = $sheet->getCell('C1')->getValue();
            $arrival_time  = (trim($sheet->getCell('C1')->getValue() - 25569) * 86400);
            $model         = (new SailScheduleModel())->where('ship_name', $ship_name)
                ->where('voyage', $voyage)
                ->find();
            if (!$model) {
                $model                  = new SailScheduleModel();
                $model->ship_name       = $ship_name;
                $model->voyage          = $voyage;
                $model->arrival_time    = date('Y-m-d H:i:s', $arrival_time);
                $model->ship_company_id = 2;
                $model->save();
            }
            for ($row = 2; $row <= $highestRow; $row++) //行号从1开始
            {
                for ($column = 'A'; $column <= $highestColumm; $column++) //列数是以A列开始
                {
                    $data[$row - 2][] = trim($sheet->getCell($column . $row)->getValue());
                    //                    if (empty($data[$row]) == false) {
                    //
                    //                         = $str;
                    ////                        if (strlen($str)>11) {
                    ////                            $pieces = explode("|", $str);
                    ////                            $data[$row][] = $pieces[0];
                    ////                        }else{
                    ////                            ['mobile'] = $str;
                    ////                        }
                    //                    } else {
                    //                        $data[$row]['name'] = $sheet->getCell($column . $row)->getValue();
                    //                    }
                }
            }
            foreach ($data as $key => &$datum) {
                if (empty($datum[0]) && empty($datum[1]) && empty($datum[2]) && empty($datum[3]) && empty($datum[4]) && empty($datum[5])) {
                    unset($data[$key]);
                }
            }
            foreach ($data as $item) {
                if ((new SeaWaybillModel())->where('sea_waybill_number', $item[0])
                    ->where('case_number', $item[1])
                    ->find()) {
                    throw new RuntimeException(['msg' => '出现相同的箱号']);
                }
                $Smodel                     = new SeaWaybillModel();
                $Smodel->sail_schedule_id   = $model->getData('id');
                $Smodel->ship_company_id    = 2;
                $Smodel->sea_waybill_number = $item[0];
                $Smodel->case_number        = $item[1];
                $Smodel->box                = $item[4];
                $Smodel->goods_name         = $item[2];
                $Smodel->towing_fee         = $item[3];
                $Smodel->receiver_address   = $item[5];
                $temp                       = explode(' ', $item[6]);
                $temp2                      = [];
                foreach ($temp as $t) {
                    if (!empty($t)) {
                        $temp2[] = $t;
                    }
                }
                if (count($temp2) === 2) {
                    $Smodel->receiver               = trim($temp2[0]);
                    $Smodel->receiver_mobile_number = trim($temp2[1]);
                }
                else {
                    $Smodel->receiver               = $item[6];
                    $Smodel->receiver_mobile_number = $item[6];
                }
                $Smodel->need_receipt        = '0';
                $Smodel->type                = 'import';
                $Smodel->fh_status           = true;
                $Smodel->estimated_timestamp = date('Y-m-d H:i:s', (trim($item[8] - 25569) * 86400));
                $Smodel->save();
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }

        dump($data);
        die;
    }

    public function postCheckZhongguSeaWaybill()
    {
        //检查所有的船期是否正确
        Db::startTrans();
        try {
            $title = '湛江运丰6月份拖车费账单';
            //            $spreadsheet   = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
            //            $reader        = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');            //设置以Excel5格式(Excel97-2003工作簿)
            //            $PHPExcel      = $reader->load($title.'.xlsx');                                    // 载入excel文件
            //            $sheet         = $PHPExcel->getSheet(0);                                               // 读取第一個工作表
            //            $highestRow    = $sheet->getHighestRow();                                              // 取得总行数
            //            $highestColumm = $sheet->getHighestColumn();                                           // 取得总列数
            //            $data          = [];
            //            for ($row = 4; $row <= $highestRow; $row++) //行号从1开始
            //            {
            //                for ($column = 'A'; $column <= $highestColumm; $column++) //列数是以A列开始
            //                {
            //                    $data[$row - 2][] = trim($sheet->getCell($column . $row)->getValue());
            //                    //                    if (empty($data[$row]) == false) {
            //                    //
            //                    //                         = $str;
            //                    ////                        if (strlen($str)>11) {
            //                    ////                            $pieces = explode("|", $str);
            //                    ////                            $data[$row][] = $pieces[0];
            //                    ////                        }else{
            //                    ////                            ['mobile'] = $str;
            //                    ////                        }
            //                    //                    } else {
            //                    //                        $data[$row]['name'] = $sheet->getCell($column . $row)->getValue();
            //                    //                    }
            //                }
            //            }
            //            foreach ($data as $key => &$datum) {
            //                if (empty($datum[0]) && empty($datum[1]) && empty($datum[2]) && empty($datum[3]) && empty($datum[4]) && empty($datum[5])) {
            //                    unset($data[$key]);
            //                }
            //            }
            //            file_put_contents($title.'.txt', serialize($data));
            //            var_dump($data);
            //            die;

            $fp      = fopen($title . '.txt', 'r');                       //读
            $data    = unserialize(fread($fp, filesize($title . '.txt')));//反序列化，并赋值
            $temp    = [];
            $bill_id = 100003;
            //            var_dump($data);die;
            foreach ($data as $v) {
                //                                var_dump($v);die;
                $v[1]  = trim($v[1]);
                $v[2]  = trim($v[2]);
                $v[3]  = trim($v[3]);
                $v[4]  = trim($v[4]);
                $v[6]  = trim($v[6]);
                $v[12] = trim($v[12]);
                $v[16] = trim($v[16]);
                //$v[1] G20071946900
                //$v[2] 畅锦18/2038S
                //$v[3] 40HC
                //$v[4] BEAU4880447
                //$v[6] 1680.00
                //$v[12] 进口出口
                //$v[16] 廉江市石城镇石南管区新枝坑村
                if ($v[12] === '进口') {
                    $sModel = (new SeaWaybillModel())->where('sea_waybill_number', $v[1])
                        ->with(['sailScheduleInfo'])
                        ->where('case_number', $v[4])
                        ->find();
                    if (!$sModel) {
                        throw new RuntimeException(['msg' => $v[1] . ' - ' . $v[4] . '箱号不存在']);
                    }
                    $sArrModel = $sModel->toArray();
                    if ($sArrModel['sailScheduleInfo']['ship_name'] . '/' . $sArrModel['sailScheduleInfo']['voyage'] !== $v[2]) {
                        $ship_name_voyage = explode('/', $v[2]);
                        $model            = (new SailScheduleModel())->where('ship_name', trim($ship_name_voyage[0]))
                            ->where('voyage', trim($ship_name_voyage[1]))
                            ->find();
                        if (!$model) {
                            $model                  = new SailScheduleModel();
                            $model->ship_name       = trim($ship_name_voyage[0]);
                            $model->voyage          = trim($ship_name_voyage[1]);
                            $model->ship_company_id = 2;
                            $model->save();
                        }
                        $sModel->sail_schedule_id = $model->getData('id');
                        //                    var_dump($sArrModel['sailScheduleInfo']['ship_name'] . '/' . $sArrModel['sailScheduleInfo']['voyage'],$v[2]);
                        //                    throw new RuntimeException(['msg' => $v[1] . ' - ' . $v[4] . ' - ' . $v[2] . '船期不正确']);
                    }
                    $temp[]          = $v;
                    $sModel->bill_id = $bill_id;
                    $sModel->save();
                }
                else {
                    $sModel = (new SeaWaybillModel())->where('sea_waybill_number', $v[1])
                        ->with(['sailScheduleInfo'])
                        ->where('case_number', $v[4])
                        ->find();
                    if ($sModel) {
                        $sModel->bill_id = $bill_id;
                        $sModel->save();
                    }
                    else {
                        $ship_name_voyage = explode('/', $v[2]);
                        $model            = (new SailScheduleModel())->where('ship_name', trim($ship_name_voyage[0]))
                            ->where('voyage', trim($ship_name_voyage[1]))
                            ->find();
                        if (!$model) {
                            $model                  = new SailScheduleModel();
                            $model->ship_name       = trim($ship_name_voyage[0]);
                            $model->voyage          = trim($ship_name_voyage[1]);
                            $model->ship_company_id = 2;
                            $model->save();
                        }
                        //                        $v[1]  = trim($v[1]);
                        //                        $v[2]  = trim($v[2]);
                        //                        $v[3]  = trim($v[3]);
                        //                        $v[4]  = trim($v[4]);
                        //                        $v[6]  = trim($v[6]);
                        //                        $v[12] = trim($v[12]);
                        //                        $v[16] = trim($v[16]);
                        //                        //$v[1] G20071946900
                        //                        //$v[2] 畅锦18/2038S
                        //                        //$v[3] 40HC
                        //                        //$v[4] BEAU4880447
                        //                        //$v[6] 1680.00
                        //                        //$v[8] 进口出口
                        //                        //$v[16] 廉江市石城镇石南管区新枝坑村
                        $exportModel                         = new SeaWaybillModel();
                        $exportModel->ship_company_id        = 2;
                        $exportModel->sail_schedule_id       = $model->getData('id');
                        $exportModel->sea_waybill_number     = $v[1];
                        $exportModel->box                    = $v[3];
                        $exportModel->receiver_address       = $v[16];
                        $exportModel->case_number            = $v[4];
                        $exportModel->qf_number              = '';
                        $exportModel->goods_name             = '';
                        $exportModel->towing_fee             = $v[6];
                        $exportModel->other_fee_desc         = '';
                        $exportModel->need_receipt           = '0';
                        $exportModel->need_poundbill         = '0';
                        $exportModel->status                 = MainEnum::SEA_WAYBILL_STATUS_UN_DISPATCH_CAR;
                        $exportModel->car_id                 = null;
                        $exportModel->car_fee                = 0.00;
                        $exportModel->other_fee              = 0.00;
                        $exportModel->weight                 = null;
                        $exportModel->type                   = 'export';
                        $exportModel->receiver               = '';
                        $exportModel->receiver_mobile_number = '';
                        $exportModel->remark                 = '';
                        $exportModel->dz_user_id             = null;
                        $exportModel->fh_status              = '1';
                        $exportModel->bill_id                = $bill_id;
                        $exportModel->save();
                        $temp[] = $v;
                    }
                }
            }
            Db::commit();
            var_dump($temp);
            die;
            $ship_name    = trim($sheet->getCell('A1')->getValue());
            $voyage       = trim($sheet->getCell('B1')->getValue());
            $c            = $sheet->getCell('C1')->getValue();
            $arrival_time = (trim($sheet->getCell('C1')->getValue() - 25569) * 86400);
            $model        = (new SailScheduleModel())->where('ship_name', $ship_name)->where('voyage', $voyage)->find();
            if (!$model) {
                $model                  = new SailScheduleModel();
                $model->ship_name       = $ship_name;
                $model->voyage          = $voyage;
                $model->arrival_time    = date('Y-m-d H:i:s', $arrival_time);
                $model->ship_company_id = 2;
                $model->save();
            }
            foreach ($data as $item) {
                if ((new SeaWaybillModel())->where('sea_waybill_number', $item[0])
                    ->where('case_number', $item[1])
                    ->find()) {
                    throw new RuntimeException(['msg' => '出现相同的箱号']);
                }
                $Smodel                     = new SeaWaybillModel();
                $Smodel->sail_schedule_id   = $model->getData('id');
                $Smodel->ship_company_id    = 2;
                $Smodel->sea_waybill_number = $item[0];
                $Smodel->case_number        = $item[1];
                $Smodel->box                = $item[4];
                $Smodel->goods_name         = $item[2];
                $Smodel->towing_fee         = $item[3];
                $Smodel->receiver_address   = $item[5];
                $temp                       = explode(' ', $item[6]);
                $temp2                      = [];
                foreach ($temp as $t) {
                    if (!empty($t)) {
                        $temp2[] = $t;
                    }
                }
                if (count($temp2) === 2) {
                    $Smodel->receiver               = trim($temp2[0]);
                    $Smodel->receiver_mobile_number = trim($temp2[1]);
                }
                else {
                    $Smodel->receiver               = $item[6];
                    $Smodel->receiver_mobile_number = $item[6];
                }
                $Smodel->need_receipt        = '0';
                $Smodel->type                = 'import';
                $Smodel->fh_status           = true;
                $Smodel->estimated_timestamp = date('Y-m-d H:i:s', (trim($item[8] - 25569) * 86400));
                $Smodel->save();
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }

        dump($data);
        die;
    }
}